package com.weifly.weistock.module.stockdata.impl;

import com.weifly.weistock.core.config.AbstractConfigService;
import com.weifly.weistock.core.config.ConfigConstants;
import com.weifly.weistock.core.constant.StockCatalogEnum;
import com.weifly.weistock.core.market.bo.StockDayBO;
import com.weifly.weistock.core.market.bo.StockDividendBO;
import com.weifly.weistock.core.market.bo.StockKLineBO;
import com.weifly.weistock.module.stockdata.StockDataStoreService;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据存储服务实现
 *
 * @author weifly
 * @since 2021/6/11
 */
public class StockDataStoreServiceImpl extends AbstractConfigService implements StockDataStoreService {

    @Override
    public List<StockKLineBO> loadStockDataList() {
        List<StockKLineBO> stockList = new ArrayList<>();
        for (File xmlFile : this.getConfigFolder().listFiles()) {
            if (xmlFile.getName().endsWith(".xml")) {
                log.info("加载股票数据：" + xmlFile.getAbsolutePath());
                StockKLineBO stockKLineBO = this.loadDataXml(xmlFile);
                stockList.add(stockKLineBO);
            }
        }
        return stockList;
    }

    @Override
    public StockKLineBO loadStockData(String stockCode) {
        File xmlFile = new File(this.getConfigFolder(), this.makeXmlFileName(stockCode));
        if (!xmlFile.exists()) {
            log.info("股票数据文件不存在：" + xmlFile.getAbsolutePath());
            return null;
        }
        log.info("加载股票数据：" + xmlFile.getAbsolutePath());
        return this.loadDataXml(xmlFile);
    }

    private StockKLineBO loadDataXml(File xmlFile) {
        StockKLineBO stockKLineBO = new StockKLineBO();
        try {
            SAXReader reader = new SAXReader();
            Document document = reader.read(xmlFile);
            Element rootEle = document.getRootElement();

            String stockCode = rootEle.attributeValue(ConfigConstants.ATTR_STOCK_CODE);
            stockKLineBO.setStockCode(stockCode);
            String stockName = rootEle.attributeValue(ConfigConstants.ATTR_STOCK_NAME);
            stockKLineBO.setStockName(stockName);
            String stockCatalog = rootEle.attributeValue(ConfigConstants.ATTR_STOCK_CATALOG);
            stockKLineBO.setStockCatalog(StockCatalogEnum.getByName(stockCatalog));

            // 分红信息
            Element stockDividendsEle = rootEle.element("stockDividends");
            if (stockDividendsEle != null) {
                List<Element> stockDividendEleList = stockDividendsEle.elements("stockDividend");
                if (stockDividendEleList != null && stockDividendEleList.size() > 0) {
                    for (Element dividendEle : stockDividendEleList) {
                        StockDividendBO dividendBO = new StockDividendBO();
                        dividendBO.setStockCode(stockCode);
                        dividendBO.setDay(dividendEle.attributeValue(ConfigConstants.ATTR_DAY));
                        String dividendAmountStr = dividendEle.attributeValue("dividendAmount");
                        if (StringUtils.isNotBlank(dividendAmountStr)) {
                            dividendBO.setDividendAmount(Double.valueOf(dividendAmountStr));
                        }
                        String dividendStockStr = dividendEle.attributeValue("dividendStock");
                        if (StringUtils.isNotBlank(dividendStockStr)) {
                            dividendBO.setDividendStock(Integer.valueOf(dividendStockStr));
                        }
                        stockKLineBO.getDividendList().add(dividendBO);
                    }
                }
            }

            List<Element> recordEleList = rootEle.elements(ConfigConstants.ELE_RECORD);
            if (recordEleList != null) {
                for (Element recordEle : recordEleList) {
                    StockDayBO dayBO = new StockDayBO();
                    String day = recordEle.attributeValue(ConfigConstants.ATTR_DAY);
                    dayBO.setDay(day);

                    String openStr = recordEle.attributeValue(ConfigConstants.ATTR_OPEN);
                    double open = Double.parseDouble(openStr);
                    dayBO.setOpen(open);

                    String highStr = recordEle.attributeValue(ConfigConstants.ATTR_HIGH);
                    double high = Double.parseDouble(highStr);
                    dayBO.setHigh(high);

                    String lowStr = recordEle.attributeValue(ConfigConstants.ATTR_LOW);
                    double low = Double.parseDouble(lowStr);
                    dayBO.setLow(low);

                    String closeStr = recordEle.attributeValue(ConfigConstants.ATTR_CLOSE);
                    double close = Double.parseDouble(closeStr);
                    dayBO.setClose(close);

                    // 除权信息
                    String frontOpenStr = recordEle.attributeValue("front_open");
                    if (StringUtils.isNotBlank(frontOpenStr)) {
                        dayBO.setFront_open(Double.valueOf(frontOpenStr));
                    }
                    String frontHighStr = recordEle.attributeValue("front_high");
                    if (StringUtils.isNotBlank(frontHighStr)) {
                        dayBO.setFront_high(Double.valueOf(frontHighStr));
                    }
                    String frontLowStr = recordEle.attributeValue("front_low");
                    if (StringUtils.isNotBlank(frontLowStr)) {
                        dayBO.setFront_low(Double.valueOf(frontLowStr));
                    }
                    String frontCloseStr = recordEle.attributeValue("front_close");
                    if (StringUtils.isNotBlank(frontCloseStr)) {
                        dayBO.setFront_close(Double.valueOf(frontCloseStr));
                    }
                    stockKLineBO.getDayList().add(dayBO);
                }
            }
            return stockKLineBO;
        } catch (DocumentException e) {
            log.error("", e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public void saveStockData(StockKLineBO stockKLineBO) {
        DocumentFactory factory = DocumentFactory.getInstance();
        Document document = factory.createDocument();
        document.setXMLEncoding("UTF8");

        Element rootEle = factory.createElement(ConfigConstants.ELE_ROOT);
        rootEle.addAttribute(ConfigConstants.ATTR_STOCK_CODE, stockKLineBO.getStockCode());
        rootEle.addAttribute(ConfigConstants.ATTR_STOCK_NAME, stockKLineBO.getStockName());
        rootEle.addAttribute(ConfigConstants.ATTR_STOCK_CATALOG, stockKLineBO.getStockCatalog().name());
        document.setRootElement(rootEle);

        // 分红信息
        Element stockDividendsEle = factory.createElement("stockDividends");
        rootEle.add(stockDividendsEle);
        for (StockDividendBO stockDividendBO : stockKLineBO.getDividendList()) {
            Element dividendEle = factory.createElement("stockDividend");
            dividendEle.addAttribute(ConfigConstants.ATTR_DAY, stockDividendBO.getDay());
            if (stockDividendBO.getDividendAmount() != null) {
                dividendEle.addAttribute("dividendAmount", String.valueOf(stockDividendBO.getDividendAmount()));
            }
            if (stockDividendBO.getDividendStock() != null) {
                dividendEle.addAttribute("dividendStock", String.valueOf(stockDividendBO.getDividendStock()));
            }
            stockDividendsEle.add(dividendEle);
        }

        for (StockDayBO dayBO : stockKLineBO.getDayList()) {
            Element recordEle = factory.createElement(ConfigConstants.ELE_RECORD);
            recordEle.addAttribute(ConfigConstants.ATTR_DAY, dayBO.getDay());
            recordEle.addAttribute(ConfigConstants.ATTR_OPEN, String.valueOf(dayBO.getOpen()));
            recordEle.addAttribute(ConfigConstants.ATTR_HIGH, String.valueOf(dayBO.getHigh()));
            recordEle.addAttribute(ConfigConstants.ATTR_LOW, String.valueOf(dayBO.getLow()));
            recordEle.addAttribute(ConfigConstants.ATTR_CLOSE, String.valueOf(dayBO.getClose()));
            // 除权信息
            if (dayBO.getFront_open() != null) {
                recordEle.addAttribute("front_open", String.valueOf(dayBO.getFront_open()));
            }
            if (dayBO.getFront_high() != null) {
                recordEle.addAttribute("front_high", String.valueOf(dayBO.getFront_high()));
            }
            if (dayBO.getFront_low() != null) {
                recordEle.addAttribute("front_low", String.valueOf(dayBO.getFront_low()));
            }
            if (dayBO.getFront_close() != null) {
                recordEle.addAttribute("front_close", String.valueOf(dayBO.getFront_close()));
            }
            rootEle.add(recordEle);
        }

        File xmlFile = new File(this.getConfigFolder(), this.makeXmlFileName(stockKLineBO.getStockCode()));
        log.info("保存股票数据, file={}", xmlFile.getAbsolutePath());
        this.saveConfig(xmlFile, document);
    }

    private String makeXmlFileName(String stockCode) {
        return "stock_" + stockCode + ".xml";
    }
}
